package YAPserver.score;

import java.util.HashMap;
import java.util.Observable;

import YAPenvironment.YAPconstant;
import YAPserver.logic.Output;
import YAPserver.logic.Player;

/**
 * This class lists and gives all the various awards to the players in the GameLogic.
 * @author Daniel
 *
 */
public class EndScore extends Observable{	
	private static final int minBounceCount = 10; //min number of bounces needed to get this award
	private static final int minShopCount = 10; //min number of mods caught needed to get this award
	
	/**
	 * Constructs the endScore linked to the output.
	 * @param out output to be linked
	 */
	public EndScore(Output out){
		this.addObserver(out);
	}
	/**
	 * Gives Awards to all the players (if they got one) and sends the information to the output.
	 * @param players hashMap of players to whom awards are given
	 * @return gameId (Integer) of the receiver of the star award/bad winner award
	 */
	public int giveAwards(HashMap<Integer, Player> players){
		//coward award given first to make sure he/she doesn't get any good awards
		giveCowardAward(players);
		giveBunnyAward(players);
		giveShoppingAward(players);
		giveChronosAward(players);
		int winner = giveStarAward(players);
		
		stringifyAwards(players);
		
		return winner;
	}
	private void giveBunnyAward(HashMap<Integer, Player> players){
		int playerId = -1;
		int mostBounces = minBounceCount;
		for(int id: players.keySet()){
			int playersBounces = players.get(id).getScore(CountingAward.Bunny);
			if(playersBounces > mostBounces){
				playerId = id;
				mostBounces = playersBounces;
			}
		}
		if(players.containsKey(playerId)){
			players.get(playerId).giveAward(CountingAward.Bunny);
		}
	}
	
	private void giveCowardAward(HashMap<Integer, Player> players){
		double longestWall = 0;
		//first get the longestWall
		for(int id: players.keySet()){
			double wallLength = players.get(id).getWall().getLine().getLength();
			if(wallLength > longestWall){
				longestWall = wallLength;
			}
		}
		//now give cowardAward
		for(int id: players.keySet()){
			double wallLength = players.get(id).getWall().getLine().getLength();
			if(wallLength*2 < longestWall){
				players.get(id).giveAward(CountingAward.Coward);
			}
		}
	}
	
	private void giveShoppingAward(HashMap<Integer, Player> players){
		int playerId = -1;
		int mostShopping = minShopCount;
		for(int id: players.keySet()){
			int playersShopping = players.get(id).getScore(CountingAward.Shopping);
			if(playersShopping > mostShopping){
				playerId = id;
				mostShopping = playersShopping;
			}
		}
		if(players.containsKey(playerId)){
			players.get(playerId).giveAward(CountingAward.Shopping);
		}
	}
	
	//all awards given to the winner
	private int giveStarAward(HashMap<Integer, Player> players){
		for(int id: players.keySet()){
			if(players.get(id).getLives() >= YAPconstant.C_MINLIVES){
				if(players.get(id).getAward().isEmpty()){
					players.get(id).giveAward(CountingAward.Star);
				}else if(players.get(id).getAward().get(0) == CountingAward.Coward){
					players.get(id).giveAward(CountingAward.BadWinner);
				}else{
					players.get(id).giveAward(CountingAward.Star);
				}	
				return id;
			}
		}
		//if there's no winner
		return -1;
	}
	//Gives awards according to length of time spent in game.
	private void giveChronosAward(HashMap<Integer, Player> players){
		for(int id: players.keySet()){
			if(players.get(id).getScore(CountingAward.Chronos) > 0){
				players.get(id).giveAward(CountingAward.Chronos);
			}
		}
	}
	
	private void stringifyAwards(HashMap<Integer, Player> players){
		String highScore="";
		for(Award award: CountingAward.values()){
			for(int id: players.keySet()){
				if(players.get(id).getAward().contains(award)){
					highScore = highScore + players.get(id).getName() + " " + award + YAPconstant.C_SEPARATOR;
				}
			}
		}
		//if there are more types of awards their enums should be cycled through too.
//		System.out.println(highScore);
		this.setChanged();
		this.notifyObservers(highScore);
	}
}
